package com.example.admin.mybledemo.ota;

import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import cn.com.heaton.blelibrary.ble.BleLog;

import java.util.UUID;

import cn.com.heaton.blelibrary.ble.Ble;
import cn.com.heaton.blelibrary.ble.BleLog;
import cn.com.heaton.blelibrary.ble.callback.BleScanCallback;
import cn.com.heaton.blelibrary.ble.callback.wrapper.BleWrapperCallback;
import cn.com.heaton.blelibrary.ble.model.BleDevice;

public class BleCommunicator extends BleWrapperCallback<BleDevice> {

    private static final String TAG = "BleCommunicator";
    private CommunicationCallback callback;

    public interface CommunicationCallback {
        void onConnected(BleDevice device);
        void onDisconnected(BleDevice device);
        void onConnectFailed(BleDevice device, int errorCode);
        void onServicesDiscovered(BleDevice device);
        void onCharacteristicRead(BleDevice device, BluetoothGattCharacteristic characteristic);
        void onCharacteristicWrite(BleDevice device, BluetoothGattCharacteristic characteristic);
        void onWriteFailed(BleDevice device, int errorCode);
        void onCharacteristicChanged(BleDevice device, BluetoothGattCharacteristic characteristic);
        void onDescriptorWriteSuccess(BleDevice device, BluetoothGattDescriptor descriptor);
        void onMtuChanged(BleDevice device, int mtu, int status);
        void onReadRemoteRssi(BleDevice device, int rssi, int status);
    }

    public BleCommunicator(CommunicationCallback callback) {
        this.callback = callback;
        BleLog.d(TAG, "BleCommunicator 构造函数被调用，callback: " + (callback != null ? "非空" : "null"));
    }

    public void connect(BleDevice device) {
        BleLog.d(TAG, "Attempting to connect to device: " + device.getBleName() + " (" + device.getBleAddress() + ")");
        
        // *** 关键修复：在每次连接前强制禁用自动重连 ***
        // 因为BLE库的connect()方法会重新设置device.setAutoConnect(Ble.options().autoConnect)
        try {
            // 在连接前强制设置为false
            device.setAutoConnect(false);
            BleLog.d(TAG, "连接前强制禁用设备自动重连: " + device.getBleName());
        } catch (Exception e) {
            BleLog.e(TAG, "禁用自动重连失败: " + e.getMessage());
        }
        
        Ble.getInstance().connect(device, null); // Use global callback
        
        // *** 连接后再次确认禁用 ***
        try {
            device.setAutoConnect(false);
            Ble.getInstance().autoConnect(device, false);
            BleLog.d(TAG, "连接后再次确认禁用自动重连: " + device.getBleName());
        } catch (Exception e) {
            BleLog.e(TAG, "连接后禁用自动重连失败: " + e.getMessage());
        }
    }

    public void disconnect(BleDevice device) {
        Ble.getInstance().disconnect(device);
    }

    public void readCharacteristic(BleDevice device, String serviceUuid, String characteristicUuid) {
        BleLog.d(TAG, "Reading characteristic: " + characteristicUuid + " from service: " + serviceUuid);
        Ble.getInstance().readByUuid(device, UUID.fromString(serviceUuid), UUID.fromString(characteristicUuid), null);
    }

    public void writeCharacteristic(BleDevice device, String serviceUuid, String characteristicUuid, byte[] data) {
        BleLog.d(TAG, "Writing to characteristic: " + characteristicUuid + " on service: " + serviceUuid);
        
        // 添加数据内容调试
        if (data != null) {
            StringBuilder hexString = new StringBuilder();
            StringBuilder asciiString = new StringBuilder();
            for (byte b : data) {
                hexString.append(String.format("%02X ", b));
                char c = (char) (b & 0xFF);
                asciiString.append(Character.isISOControl(c) ? '.' : c);
            }
            BleLog.d(TAG, ">>> 写入数据长度: " + data.length + " 字节");
            BleLog.d(TAG, ">>> 写入数据(HEX): " + hexString.toString());
            BleLog.d(TAG, ">>> 写入数据(ASCII): " + asciiString.toString());
        } else {
            BleLog.e(TAG, ">>> 写入数据为空!");
        }
        
        // 将UUID转换为小写，以匹配BLE服务发现时的格式
        String serviceUuidLower = serviceUuid.toLowerCase();
        String characteristicUuidLower = characteristicUuid.toLowerCase();
        BleLog.d(TAG, ">>> 转换后的服务UUID: " + serviceUuidLower);
        BleLog.d(TAG, ">>> 转换后的特征UUID: " + characteristicUuidLower);
        
        Ble.getInstance().writeByUuid(device, data, UUID.fromString(serviceUuidLower), UUID.fromString(characteristicUuidLower), null);
    }

    public void enableNotification(BleDevice device, String serviceUuid, String characteristicUuid) {
        BleLog.d(TAG, "Enabling notification for characteristic: " + characteristicUuid + " on service: " + serviceUuid);
        Ble.getInstance().enableNotifyByUuid(device, true, UUID.fromString(serviceUuid), UUID.fromString(characteristicUuid), null);
    }

    public void disableNotification(BleDevice device, String serviceUuid, String characteristicUuid) {
        BleLog.d(TAG, "Disabling notification for characteristic: " + characteristicUuid + " on service: " + serviceUuid);
        Ble.getInstance().enableNotifyByUuid(device, false, UUID.fromString(serviceUuid), UUID.fromString(characteristicUuid), null);
    }

    public void startScan(BleScanCallback<BleDevice> scanCallback) {
        Ble.getInstance().startScan(scanCallback);
    }

    public void stopScan() {
        Ble.getInstance().stopScan();
    }

    // BleWrapperCallback overrides
    @Override
    public void onConnectionChanged(BleDevice device) {
        super.onConnectionChanged(device);
        if (device.isConnected()) {
            BleLog.d(TAG, "onConnectionChanged: Connected to " + device.getBleName());
            BleLog.d(TAG, "*** 即将调用 callback.onConnected ***");
            if (callback != null) {
            callback.onConnected(device);
                BleLog.d(TAG, "*** callback.onConnected 已调用 ***");
            } else {
                BleLog.e(TAG, "*** callback 为 null! ***");
            }
        } else if (device.isDisconnected()) {
            BleLog.d(TAG, "onConnectionChanged: Disconnected from " + device.getBleName());
            callback.onDisconnected(device);
        }
    }

    @Override
    public void onServicesDiscovered(BleDevice device, BluetoothGatt gatt) {
        super.onServicesDiscovered(device, gatt);
        BleLog.d(TAG, "onServicesDiscovered: Services discovered for " + device.getBleName());
        BleLog.d(TAG, "*** 即将调用 callback.onServicesDiscovered ***");
        if (callback != null) {
        callback.onServicesDiscovered(device);
            BleLog.d(TAG, "*** callback.onServicesDiscovered 已调用 ***");
        } else {
            BleLog.e(TAG, "*** callback 为 null! ***");
        }
    }

    @Override
    public void onReadSuccess(BleDevice device, BluetoothGattCharacteristic characteristic) {
        super.onReadSuccess(device, characteristic);
        BleLog.d(TAG, "onReadSuccess: Read from " + characteristic.getUuid().toString());
        BleLog.d(TAG, "*** 即将调用 callback.onCharacteristicRead ***");
        if (callback != null) {
            callback.onCharacteristicRead(device, characteristic);
            BleLog.d(TAG, "*** callback.onCharacteristicRead 已调用 ***");
        } else {
            BleLog.e(TAG, "*** callback 为 null! ***");
        }
    }

    @Override
    public void onReadFailed(BleDevice device, int failedCode) {
        super.onReadFailed(device, failedCode);
        BleLog.e(TAG, "onReadFailed: Read failed with error code: " + failedCode);
        
        // 读取失败的具体处理
        String errorMessage = "读取失败";
        switch (failedCode) {
            case 133: // GATT_ERROR
                errorMessage = "GATT错误(133): 特征值读取被设备拒绝";
                break;
            case 8: // GATT_INSUFFICIENT_AUTHENTICATION
                errorMessage = "认证不足(8): 设备要求更高级别的认证";
                break;
            case 15: // GATT_INSUFFICIENT_ENCRYPTION
                errorMessage = "加密不足(15): 需要加密连接";
                break;
            default:
                errorMessage = "读取失败，错误码: " + failedCode;
                break;
        }
        
        BleLog.e(TAG, "特征值读取失败: " + errorMessage);
        // 通知状态机读取失败
        if (callback != null) {
            callback.onConnectFailed(device, failedCode); // 暂时使用onConnectFailed，后续可以添加专门的读取失败回调
        }
    }

    @Override
    public void onWriteSuccess(BleDevice device, BluetoothGattCharacteristic characteristic) {
        super.onWriteSuccess(device, characteristic);
        BleLog.d(TAG, "onWriteSuccess: Wrote to " + characteristic.getUuid().toString());
        callback.onCharacteristicWrite(device, characteristic);
    }

    @Override
    public void onWriteFailed(BleDevice device, int errorCode) {
        super.onWriteFailed(device, errorCode);
        BleLog.e(TAG, "onWriteFailed: Write failed with error code: " + errorCode);
        
        // 写入失败的具体处理
        String errorMessage = "写入失败";
        switch (errorCode) {
            case 133: // GATT_ERROR
                errorMessage = "升级命令已发送，设备正在重启进入Boot模式...";
                break;
            case 8: // GATT_INSUFFICIENT_AUTHENTICATION
                errorMessage = "认证不足(8): 设备要求更高级别的认证";
                break;
            case 15: // GATT_INSUFFICIENT_ENCRYPTION
                errorMessage = "加密不足(15): 需要加密连接";
                break;
            default:
                errorMessage = "写入失败，错误码: " + errorCode;
                break;
        }
        
        // 通知状态机写入失败
        if (callback != null) {
            BleLog.e(TAG, "升级过程中写入失败: " + errorMessage);
            callback.onWriteFailed(device, errorCode);
        }
    }

    @Override
    public void onChanged(BleDevice device, BluetoothGattCharacteristic characteristic) {
        super.onChanged(device, characteristic);
        BleLog.d(TAG, "onChanged: Notification from " + characteristic.getUuid().toString());
        callback.onCharacteristicChanged(device, characteristic);
    }

    @Override
    public void onConnectFailed(BleDevice device, int errorCode) {
        super.onConnectFailed(device, errorCode);
        BleLog.e(TAG, "*** BleCommunicator.onConnectFailed 被调用 ***");
        BleLog.e(TAG, "onConnectFailed: Failed to connect to " + device.getBleName() + ", code: " + errorCode);
        BleLog.e(TAG, "*** 即将调用 callback.onConnectFailed ***");
        if (callback != null) {
        callback.onConnectFailed(device, errorCode);
            BleLog.e(TAG, "*** callback.onConnectFailed 已调用 ***");
        } else {
            BleLog.e(TAG, "*** callback 为 null! ***");
        }
    }

    @Override
    public void onDescWriteSuccess(BleDevice device, BluetoothGattDescriptor descriptor) {
        super.onDescWriteSuccess(device, descriptor);
        BleLog.d(TAG, "onDescriptorWriteSuccess: Descriptor written for " + descriptor.getUuid().toString());
        callback.onDescriptorWriteSuccess(device, descriptor);
    }

    @Override
    public void onMtuChanged(BleDevice device, int mtu, int status) {
        super.onMtuChanged(device, mtu, status);
        BleLog.d(TAG, "onMtuChanged: MTU changed to " + mtu + ", status: " + status);
        callback.onMtuChanged(device, mtu, status);
    }

    public void onReadRemoteRssi(BleDevice device, int rssi, int status) {
        BleLog.d(TAG, "onReadRemoteRssi: RSSI: " + rssi + ", status: " + status);
        callback.onReadRemoteRssi(device, rssi, status);
    }
}